// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
// see COPYRIGHT for reuse legalities
//

#import "RIBTrimCurve.h"

@implementation RIBTrimCurve

+ initialize { return [RIBTrimCurve setVersion:1], self; }


- init
{
  [super init];

  return self;
}

- copyFromZone:(NXZone *)zone
{
   id   newCopy = [super copyFromZone:zone];

  NXLogError("WARNING: copyFromZone: incompletely implemented for %s : I'm leaking memory in -free", [[self class] name]);

  return newCopy;
}

- setNLoops:(RtInt)newNLoops nCurves:(RtInt *)newNCurves 
     order:(RtInt *)newOrder len:(int)newOrderLength 
     knot:(RtFloat *)newKnot len:(int)newKnotLength
     min:(RtFloat *)newMin len:(int)newMinLength  max:(RtFloat *)newMax len:(int)newMaxLength
     n2:(RtInt *)newN2 len:(int)newN2Length
     u:(RtFloat *)newU len:(int)newULength  v:(RtFloat *)newV len:(int)newVLength  w:(RtFloat *)newW len:(int)newWLength
{  
   nLoops = newNLoops;
   nCurves = newNCurves;
   order = newOrder;
   orderLength = newOrderLength;
   knot = newKnot;
   knotLength = newKnotLength;
   min = newMin;
   minLength = newMinLength;
   max = newMax;
   maxLength = newMaxLength;
   n2 = newN2;
   n2Length = newN2Length;
   u = newU;
   uLength = newULength;
   v = newV;
   vLength = newVLength;
   w = newW;
   wLength = newWLength;

   dirtyBoundingBox = TRUE;
  
   return self;
}

- renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
{
  RiTrimCurve(nLoops, nCurves, order, knot, min, max, n2, u, v, w);
  return self;
}

- writeEve:(NXStream *)stream atTabLevel:(int)tab
{
   int  i;


   for (i = 0; i < tab; i++)
   {  NXPrintf(stream, "\t");
   }
   NXPrintf(stream, "TrimCurve "); 

   NXPrintf(stream, "{ ");
   for (i = 0; i < nLoops; i++)
   {  NXPrintf(stream, "%ld ", nCurves[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < orderLength; i++)
   {  NXPrintf(stream, "%ld ", order[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < knotLength; i++)
   {  NXPrintf(stream, "%f ", knot[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < minLength; i++)
   {  NXPrintf(stream, "%f ", min[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < maxLength; i++)
   {  NXPrintf(stream, "%f ", max[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < n2Length; i++)
   {  NXPrintf(stream, "%ld ", n2[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < uLength; i++)
   {  NXPrintf(stream, "%f ", u[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < vLength; i++)
   {  NXPrintf(stream, "%f ", v[i]);
   }
   NXPrintf(stream, " } ");

   NXPrintf(stream, "{ ");
   for (i = 0; i < wLength; i++)
   {  NXPrintf(stream, "%f ", w[i]);
   }
   NXPrintf(stream, " }; ");

   return self;
}


- writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
{
   int  i, j, k, curveIndex, indexIndex, knotIndex,
        loopMax,
        pointCount = 0,
        howManyCurves = 0;
   

   for (i = 0; i < nLoops; i++)
   {  howManyCurves += nCurves[i];
   }
   for (i = 0; i < howManyCurves; i++)
   {  pointCount += n2[i];
   }

   for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "ProfileCoordinate3 {\n");
  
   j = 0;
   for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "point [%f %f %f,\n", u[j], v[j], w[j]); j++;

   while (j < (pointCount-1))
   {  for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "       %f %f %f,\n", u[j], v[j], w[j]); j++;
   }

   for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "       %f %f %f]\n", u[j], v[j], w[j]);
   for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "}\n");

   // okay, now let's define the profiles
   curveIndex = 0;

   // the first one is special, as we need to blow away any others in the state
   for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "NurbsProfile {\n");

   for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "linkage START_FIRST\n");

   indexIndex = 0;
   knotIndex = 0;
   // spit out the first knotVector
   for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "knotVector [");
   for (k = knotIndex; k < ((n2[curveIndex] + order[curveIndex]) - 1); k++)
   {  NXPrintf(stream, "%f, ", knot[k]);
   }
   NXPrintf(stream, "%f]\n", knot[k]);
   knotIndex = k + 1;

   // spit out the first set of indices into the points
   for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "index [");
   for (k = indexIndex; k < (n2[curveIndex]  - 1); k++)
   {  NXPrintf(stream, "%d, ", k);
   }
   NXPrintf(stream, "%d]\n", k);
   indexIndex = k + 1;

   for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
   NXPrintf(stream, "}\n");

   curveIndex++;

   // okay, add the rest of the curves
   while (curveIndex < howManyCurves)
   {  for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "NurbsProfile {\n");

      for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "linkage START_NEW\n");

      // spit out the first knotVector
      for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "knotVector [");
      loopMax = knotIndex + (n2[curveIndex] + order[curveIndex]) - 1;
      for (k = knotIndex; k < loopMax; k++)
      {  NXPrintf(stream, "%f, ", knot[k]);
      }
      NXPrintf(stream, "%f]\n", knot[k]);
      knotIndex = k + 1;

      // spit out the first set of indices into the points
      for (i = 0; i < (tab+1); i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "index [");
      loopMax = indexIndex + n2[curveIndex]  - 1;
      for (k = indexIndex; k < loopMax; k++)
      {  NXPrintf(stream, "%d, ", k);
      }
      NXPrintf(stream, "%d]\n", k);
      indexIndex = k + 1;

      for (i = 0; i < tab; i++) {  NXPrintf(stream, "\t"); }
      NXPrintf(stream, "}\n");

      curveIndex++;
   }

   return self;
}

#define typeVector "liiiiiiii"
#define typeValues &nLoops, &orderLength, &n2Length, &knotLength, &minLength, &maxLength, &uLength, &vLength, &wLength

- read:(NXTypedStream *)stream 
{
    int   version;

    
    [super read:stream];
    version = NXTypedStreamClassVersion(stream,"RIBTrimCurve");
    if (version == 0) NXReadTypes(stream,"i",&version), version=1;
    if (version == 1) {
	NXReadTypes(stream,typeVector,typeValues);
	
	nCurves = (long *)NXZoneMalloc([self zone], nLoops*sizeof(long));
	NXReadArray(stream, "i", nLoops, nCurves);
	order = (long *)NXZoneMalloc([self zone], orderLength*sizeof(long));
	NXReadArray(stream, "i", orderLength, order);
	n2 = (long *)NXZoneMalloc([self zone], n2Length*sizeof(long));
	NXReadArray(stream, "i", n2Length, n2);
	
	knot = (float *)NXZoneMalloc([self zone], knotLength*sizeof(float));
	NXReadArray(stream, "f", knotLength, knot);
	min = (float *)NXZoneMalloc([self zone], minLength*sizeof(float));
	NXReadArray(stream, "f", minLength, min);
	max = (float *)NXZoneMalloc([self zone], maxLength*sizeof(float));
	NXReadArray(stream, "f", maxLength, max);
	u = (float *)NXZoneMalloc([self zone], uLength*sizeof(float));
	NXReadArray(stream, "f", uLength, u);
	v = (float *)NXZoneMalloc([self zone], vLength*sizeof(float));
	NXReadArray(stream, "f", vLength, v);
	w = (float *)NXZoneMalloc([self zone], wLength*sizeof(float));
	NXReadArray(stream, "f", wLength, w);
    } else {
    }
    return self;
}

- write:(NXTypedStream *)stream 
{
    [super write:stream];
    
    NXWriteTypes(stream,typeVector, typeValues);
    
    NXWriteArray(stream, "l", nLoops, nCurves);
    NXWriteArray(stream, "l", orderLength, order);
    NXWriteArray(stream, "l", n2Length, n2);
    
    NXWriteArray(stream, "f", knotLength, knot);
    NXWriteArray(stream, "f", minLength, min);
    NXWriteArray(stream, "f", maxLength, max);
    NXWriteArray(stream, "f", uLength, u);
    NXWriteArray(stream, "f", vLength, v);
    NXWriteArray(stream, "f", wLength, w);
    
    return self;
}

@end
